//*************************************************************************************
// EGTB Generator Lowest Level Access Functions for Raw Uncompressed database files
//*************************************************************************************

#pragma once

#include "EndGameDbCommon.h"
#include "..\Engine\BinomCoef.h"

namespace EndGameDB
{
	// Memory Panic Macros => event check when RAM during generation fills up
	// Fired to free database slices from the RAM
	#define IS_MEMORY_PANIC() if(bMemoryPanicInProgress == true)
	#define DECLARE_MEMORY_PANIC() bMemoryPanicInProgress, countThreadSleep, lockMemoryPanic, g_ED

	// Database slice raw structure record
	typedef struct sub
	{
		int bm;
		int bk;
		int wm;
		int wk;
		int maxbm;
		int maxwm;
		int64 databasesize;
		uint32 *database;
		int64  db_dtm_size;
		uint8 *db_dtm;
	} subdb;

	// the currently computed database pointers
	extern uint32 *currentDb_b, *currentDb_w;		// WDL data
	extern uint8 *dtm_W, *dtm_B;					// DTM data

	// memory panic helper variables
	extern bool bMemoryPanicInProgress;
	extern int64 countThreadSleep;
	extern omp_lock_t lockMemoryPanic;

	// memory variables
	extern int64 memInUse;
	extern int64 memoryLimit; 

	// subdatabase records
	extern subdb SubDatabase[MAXPIECE+1][MAXPIECE+1][MAXPIECE+1][MAXPIECE+1][9][9][2];


	// settings functions
	void SetDatabaseRawDirectory(const wchar_t* lpDir);
	void SetDbRawMemoryLimit(int64 memoryLimitInMB);

	// low-level access functios to the raw data of databases
	bool IsSymmetric(int wm, int wk, int bm, int bk, int wmrank, int bmrank);
	
	// OpenMP versions of functions
	uint32 GetDatabaseValue(uint32 *database, int64 index);
	void SetDatabaseValue(uint32 *database, int64 index, uint32 value);
	uint8 GetDTMValue(uint8* dtm, int64 index);
	void SetDTMValue(uint8* dtm, int64 index, uint8 value);
	uint32* GetRawDatabase(int wm, int wk, int bm, int bk, int wmrank, int bmrank, int color, uint8** ppDtm);

	// Non-OpenMP versions
	uint32 GetDatabaseValueNOMP(uint32 *database, int64 index);
	void SetDatabaseValueNOMP(uint32 *database, int64 index, uint32 value);
	uint8 GetDTMValueNOMP(uint8* dtm, int64 index);
	void SetDTMValueNOMP(uint8* dtm, int64 index, uint8 value);
	uint32* GetRawDatabaseNOMP(int wm, int wk, int bm, int bk, int wmrank, int bmrank, int color, uint8** ppDtm);



	// memory panic helper functions
	void UnloadAll();
	void MemoryPanic();

	// file name creation functions
	void SetDbName(int wm, int wk, int bm, int bk, int wmrank, int bmrank, int color, wchar_t *dbname);
	void SetDbDTMName(int wm, int wk, int bm, int bk, int wmrank, int bmrank, int color, wchar_t *dbname);
	void SetDbNameState(int wm, int wk, int bm, int bk, int wmrank, int bmrank, int color, int state, wchar_t *dbname);
	void SetDbDTMNameState(int wm, int wk, int bm, int bk, int wmrank, int bmrank, int color, wchar_t *dbname, int state);


	// "power-cut" saving management of data
	// the EGTB Generator with the help of these functions is able to recover the computing state
	// from the unexpected termination
	bool CheckDbPresence(int wm, int wk, int bm, int bk, int wmrank, int bmrank);
	bool CheckStatePresence(int wm, int wk, int bm, int bk, int wmrank, int bmrank, int state);
	int FindMaximumState(int wm, int wk, int bm, int bk, int wmrank, int bmrank, int maxState);
	void DeleteStates(int wm, int wk, int bm, int bk, int wmrank, int bmrank, int maxState);
}
